import * as path from 'path';
import { Logger } from '../../../../src/logger/Logger';
import { ProjectInfo } from '../types/FuzzTypes';
import { ProjectAnalyzer } from '../../UnitTest/ProjectAnalyzer';

/**
 * Fuzz 项目信息分析器
 * 负责从源文件、BUILD.gn、ProjectAnalyzer 结果中提取项目信息
 */
export class FuzzProjectAnalyzer {
    /**
     * 提取项目信息（subsystem, module, gniImport, pathVariable）
     */
    public static extractProjectInfo(
        sourceFile: string,
        buildGnContent: string,
        sourceFileInfo?: Awaited<ReturnType<typeof ProjectAnalyzer.prototype.analyzeSourceFile>>
    ): ProjectInfo {
        let subsystem = 'unknown';
        let module = 'unknown';
        let gniImport = '';
        let pathVariable = '';
        
        // === 优先从 sourceFileInfo 的 imports 提取 ===
        if (sourceFileInfo && sourceFileInfo.sourceBuildGN) {
            const imports = sourceFileInfo.sourceBuildGN.imports || [];
            for (const imp of imports) {
                // 匹配 //subsystem/module/xxx.gni
                const match = imp.match(/^\/\/([^\/]+)\/([^\/]+)/);
                if (match && !imp.includes('//build/')) {
                    subsystem = match[1];
                    module = match[2];
                    gniImport = imp;
                    Logger.info(`[FuzzProjectAnalyzer] ✅ 从 ProjectAnalyzer 提取: ${subsystem}/${module}`);
                    break;
                }
            }
        }
        
        // === 回退：从 buildGnContent 提取 ===
        if (subsystem === 'unknown' && buildGnContent) {
            const projectNameMatch = buildGnContent.match(/import\(\"\/\/([^\/]+)\/([^\/]+)\//);
            if (projectNameMatch) {
                subsystem = projectNameMatch[1];
                module = projectNameMatch[2];
                Logger.info(`[FuzzProjectAnalyzer] ✅ 从 BUILD.gn 提取: ${subsystem}/${module}`);
            }
            
            // 提取 .gni import 路径（排除 build/）
            if (!gniImport) {
                const gniMatch = buildGnContent.match(/import\(\"(\/\/[^"]+\.gni)\"\)/);
                if (gniMatch && !gniMatch[1].includes('//build/')) {
                    gniImport = gniMatch[1];
                }
            }
        }
        
        // === 再回退：从文件路径推断 ===
        if (subsystem === 'unknown') {
            const inferred = this.inferFromFilePath(sourceFile);
            subsystem = inferred.subsystem;
            module = inferred.module;
            Logger.info(`[FuzzProjectAnalyzer] ⚠️ 从文件路径推断: ${subsystem}/${module}`);
        }
        
        // === 最后回退：使用项目根目录名推断 ===
        if (subsystem === 'unknown' && buildGnContent) {
            // 从BUILD.gn内容中的路径推断
            const pathMatch = buildGnContent.match(/\/\/([^\/]+)\/([^\/\s\)"]+)/);
            if (pathMatch) {
                subsystem = pathMatch[1];
                module = pathMatch[2];
                Logger.info(`[FuzzProjectAnalyzer] ⚠️ 从BUILD.gn路径推断: ${subsystem}/${module}`);
            }
        }
        
        // === 推断路径变量名 ===
        pathVariable = module.replace(/-/g, '_') + '_path';
        
        // === 最终验证：如果还是unknown，报警但继续 ===
        if (subsystem === 'unknown' || module === 'unknown') {
            Logger.error(`[FuzzProjectAnalyzer] ❌ 无法推断项目信息！请检查：
  1. sourceFileInfo 中是否包含 imports
  2. BUILD.gn 是否包含 import 语句
  3. 文件路径是否包含 OHCode 目录
  源文件: ${sourceFile}`);
        }
        
        Logger.info(`[FuzzProjectAnalyzer] 最终项目信息: subsystem=${subsystem}, module=${module}, gniImport=${gniImport}, pathVariable=${pathVariable}`);
        
        return {
            subsystem,
            module,
            gniImport,
            pathVariable
        };
    }

    /**
     * 从文件路径推断项目信息
     */
    private static inferFromFilePath(sourceFile: string): { subsystem: string; module: string } {
        const pathParts = sourceFile.split(path.sep);
        
        // 🔍 策略1: 优先查找 OHCode 之后的部分
        const ohCodeIndex = pathParts.findIndex(p => p.toLowerCase() === 'ohcode');
        if (ohCodeIndex >= 0 && ohCodeIndex < pathParts.length - 1) {
            const projectName = pathParts[ohCodeIndex + 1];
            // 解析项目名，如 distributedhardware_distributed_audio
            const parts = projectName.split('_');
            if (parts.length >= 2) {
                return {
                    subsystem: parts[0],
                    module: parts.slice(1).join('_')
                };
            }
        }
        
        // 🔍 策略2: 查找 code 目录（用户可能用的是 code 而非 OHCode）
        const codeIndex = pathParts.findIndex(p => p.toLowerCase() === 'code');
        if (codeIndex >= 0 && codeIndex < pathParts.length - 1) {
            const projectName = pathParts[codeIndex + 1];
            const parts = projectName.split('_');
            if (parts.length >= 2) {
                Logger.info(`[FuzzProjectAnalyzer] 从 code 目录推断: ${parts[0]}/${parts.slice(1).join('_')}`);
                return {
                    subsystem: parts[0],
                    module: parts.slice(1).join('_')
                };
            }
        }
        
        // 🔍 策略3: 尝试直接从项目目录名推断（OpenHarmony 标准命名）
        // 如 distributedhardware_distributed_audio → distributedhardware/distributed_audio
        for (const part of pathParts) {
            if (part.includes('_') && !part.startsWith('.') && part.toLowerCase() !== 'ai_dev') {
                const underscores = part.match(/_/g);
                if (underscores && underscores.length >= 1) {
                    const parts = part.split('_');
                    if (parts.length >= 2) {
                        Logger.info(`[FuzzProjectAnalyzer] 从目录名推断: ${parts[0]}/${parts.slice(1).join('_')}`);
                        return {
                            subsystem: parts[0],
                            module: parts.slice(1).join('_')
                        };
                    }
                }
            }
        }
        
        Logger.warn(`[FuzzProjectAnalyzer] ⚠️ 无法从路径推断项目信息: ${sourceFile}`);
        return {
            subsystem: 'unknown',
            module: 'unknown'
        };
    }

    /**
     * 计算 Fuzzer 相对于项目根的路径（GN格式）
     * 
     * ⚠️ 必须返回相对路径，不能包含绝对路径或 ..
     */
    public static getRelativeFuzzerPath(projectRoot: string, fuzzerDir: string): string {
        let relativePath = path.relative(projectRoot, fuzzerDir).replace(/\\/g, '/');
        
        // 🛡️ 防御性检查：如果相对路径包含 .. 或绝对路径标志，说明 projectRoot 不正确
        if (relativePath.includes('..') || path.isAbsolute(relativePath)) {
            Logger.error(`[FuzzProjectAnalyzer] ❌ 相对路径异常！
  projectRoot: ${projectRoot}
  fuzzerDir: ${fuzzerDir}
  relativePath: ${relativePath}
  
  这通常说明项目根目录推断失败！将尝试从 fuzzerDir 中提取合理的相对路径...`);
            
            // 🔧 应急修复：尝试从 fuzzerDir 中提取 test/fuzztest/ 之后的部分
            const testIndex = fuzzerDir.indexOf('test' + path.sep + 'fuzztest');
            if (testIndex >= 0) {
                relativePath = fuzzerDir.substring(testIndex).replace(/\\/g, '/');
                Logger.info(`[FuzzProjectAnalyzer] 应急路径: ${relativePath}`);
            } else {
                // 最终回退：只返回 fuzzer 目录名
                relativePath = 'test/fuzztest/' + path.basename(fuzzerDir);
                Logger.warn(`[FuzzProjectAnalyzer] 最终回退路径: ${relativePath}`);
            }
        }
        
        return relativePath;
    }
}

